package com.tuuzed.android.sqlite.internal;


import android.support.annotation.NonNull;
import android.support.annotation.Nullable;


import com.tuuzed.android.sqlite.SQLiteType;
import com.tuuzed.android.sqlite.annotation.Column;
import com.tuuzed.android.sqlite.annotation.Index;
import com.tuuzed.android.sqlite.annotation.PrimaryKey;
import com.tuuzed.android.sqlite.annotation.Transient;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class ColumnInfo {
    @NonNull
    public final String columnName;
    @NonNull
    public final String columnType;
    @Nullable
    public final Column column;
    @Nullable
    public final PrimaryKey primaryKey;
    @Nullable
    public final Index index;
    @NonNull
    public final Field field;
    @NonNull
    public final Class<?> javaType;

    @Nullable
    static ColumnInfo create(Field field) {
        if (field == null) return null;

        if (field.getAnnotation(Transient.class) != null) return null;
        int modifiers = field.getModifiers();
        // 过滤 static 属性
        if (Modifier.isStatic(modifiers)) return null;
        // 过滤 final 属性
        if (Modifier.isFinal(modifiers)) return null;
        // 过滤不支持的类型
        if (null == SQLiteType.getType(field.getType())) return null;
        return new ColumnInfo(field);
    }

    private ColumnInfo(@NonNull Field field) {
        this.field = field;
        this.javaType = field.getType();
        this.column = this.javaType.getAnnotation(Column.class);
        if (this.column == null || StringUtil.isEmpty(this.column.name())) {
            this.columnName = StringUtil.camelToUnderline(field.getName());
        } else {
            this.columnName = StringUtil.camelToUnderline(this.column.name());
        }
        //noinspection ConstantConditions
        this.columnType = SQLiteType.getType(javaType);
        index = field.getAnnotation(Index.class);
        primaryKey = field.getAnnotation(PrimaryKey.class);
    }


    /**
     * 反射获取值
     *
     * @param src 源对象
     * @return 值
     * @throws IllegalAccessException 获取失败时抛出异常
     */
    public Object getValue(Object src) throws IllegalAccessException {
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        return field.get(src);
    }

    /**
     * 反射赋值
     *
     * @param target 目标对象
     * @param value  值
     * @throws IllegalAccessException 赋值失败时抛出异常
     */
    public void setValue(Object target, Object value) throws IllegalAccessException {
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        field.set(target, value);
    }
}
